//
//  TBProcessNodeMC.h
//  TBShare
//
//  Created by JIENING ZHANG on 2020/2/25.
//  Copyright © 2020 taobao. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class TBProcessChainMC;

typedef NS_ENUM(NSInteger, TBProcessNodeMCStatus){
    TBProcessNodeMCStatusNotWork = 0,
    TBProcessNodeMCStatusWorking,
    TBProcessNodeMCStatusGoDie,
    TBProcessNodeMCStatusGoSucc
};

// 主线程执行block
void excuteInMainQueue(void (^ _Nullable block)(void));
// 非主线程执行block
void excuteInGlobleQueue(void (^ _Nullable block)(void));

void excuteInQueue(BOOL useMainQueue, void (^ _Nullable block)(void));

NS_ASSUME_NONNULL_BEGIN

@interface TBProcessNodeMC : NSObject


@property (nonatomic, assign, readonly) TBProcessNodeMCStatus processStatus;
@property (nonatomic, weak) TBProcessChainMC *processChain;

@property (nonatomic, strong) NSDate  *endWorkTs;
@property (nonatomic, strong) NSDate  *beginWorkTs;

// 是否在主线程工作
@property (nonatomic, assign) BOOL forceMainThread;

// 初始化为-1.f，如果>0, 表示开始处理后，如果超时，将godie
@property (nonatomic, assign) float timeOut4Process;

// 调试或是过程输出时节点名字，如果不设置使用，使用类名
@property (nonatomic, copy) NSString *nodeName;

//- (BOOL)isEqual:(id)object;

-(NSString *)name4log;
-(CGPoint)getNodeCordinate4Chain;

// 需要重写 默认动作是调用 goSucc
-(void) ready2work:(NSDictionary * _Nullable)startInfo;

-(void) goDie:(NSDictionary * _Nullable)dieInfo;
-(void) goSucc:(NSDictionary * _Nullable)succInfo;

// 需要重载，默认解除节点之间的相互，在处理链结束前被调用
-(void) cleanBeforeStop;

// self.processChain.processSharedInfo 线程安全存取方法
- (nullable id)safeGetSharedInfo:(nonnull id)key;
- (void)safeSetSharedInfo:(nonnull id)key value:(nullable id)value;

// 一下这些方法coder 不要使用，是给TBProcessChainMC准备的

-(void) forceBegin;

// 添加强关联的 前置节点
-(void) addStrongPreNode:(TBProcessNodeMC *)preNode;
// 添加弱关联的 前置节点
-(void) addWeakPreNode:(TBProcessNodeMC *)preNode;
// 添加前置节点
-(void) addPreNode:(TBProcessNodeMC *)preNode preStrong:(BOOL)preStrong;

// 根据串并联和强弱前置关系，推动节点行动
-(void) checkPreNodes2work:(TBProcessNodeMC *)processNode;

-(NSArray *)getPreNodeList;

// 检测有向图中是否有环, 如果有环，返回包含环的数组，最后一个元素就是环的头
// 所有访问过的 节点记录到 allNodesVisited，如果正常，应该和处理链中的node集合相同。
// 所有访问到的 没有前置节点的 node 记录到 allNodesThatNoPre，如果正常应该只有1个，且等于处理链的开始节点
// 如果是一个构建合理的处理链，所有的节点的绘制坐标（cx,cy）也一并计算好了
+ (NSArray<TBProcessNodeMC *> *) applyDFS2DetectLoopFromFinishNode:(TBProcessNodeMC *)currentNode
                      chainNodesFromFinish:(NSMutableArray<TBProcessNodeMC *> *)chainNodesFromFinish
                           allNodesVisited:(NSMutableSet<TBProcessNodeMC *> *)allNodesVisited
                         allNodesThatNoPre:(NSMutableSet<TBProcessNodeMC *> *)allNodesThatNoPre;

@end

NS_ASSUME_NONNULL_END
